# Plots for AMQP timings
require(lattice)
require(ggplot2)
require(foreach)

normal.col <- ''
special.col <- ''

# read/init data set
csv.in <- function(fname) {
	d <- read.csv(fname)
	d$t <- d$ts - min(d$ts)
	d <- d[order(d$run, d$mid),]
	return(d)
}

read2 <- function(f) {
	d <- read.csv(f, comment.char="#")
   d$s <- d$stage
   d$stage <- factor(paste(d$s, d$se, sep="-"))
   d$t <- d$ts - min(d$ts)
   return(d)
}

# panel function
pfn <- function(x,y, group.value=NULL, col.line=NULL, ...) {
    is.spc <- split.pasted(group.value, ncol=2, idx=2)[1] == "TRUE"
	cc <- ifelse(is.spc, special.col, normal.col)
	panel.xyplot(x,y, col.line=cc, ...)
}

# split space-sep. thing and pull out one column
split.pasted <- function(x, ncol=2, idx=2) {
	matrix(unlist(strsplit(as.character(x), " ", fixed=TRUE)),
	       ncol=ncol, byrow=T)[,idx]
}	

# plot points with hi==TRUE specially in the lifelines
llplot.hi <- function(z, special.color='red', 						normal.color='grey') {
	normal.col <<- normal.color
	special.col <<- special.color
	xyplot(stage ~ t, z, groups=paste(mid,hi), type='l', 		   panel=function(...) panel.superpose(panel.groups=pfn, ...),
	       xlab="Time (sec)", ylab="Stage", 
	       main=paste("Progress of each message, special messages in", special.color)
	       )
} 
# plot points in lifelines
llplot.reg <- function(d) {
		xyplot(stage ~ t, d, groups=mid, type='l', 	       xlab="Time (sec)", ylab="Stage", 
	       main=paste("Progress of each message"))
} 

# comptime
comptime <- function(d) {
	aggregate(d$ts, by = list(msg=d$mid), function(x) max(x) - min(x))
}

comptime2 <- function(d) {
	aggregate(d$ts, by = list(run=d$run, msg=d$mid), function(x) max(x) - min(x))
}

# scatterplot completion times
complot.reg <- function(d) {
	# calculate time to completion
	zi <- comptime(d)
	# plot it
	xyplot(x ~ msg, zi, xlab="message number", ylab="time to completion", type=c('g', 'p'))
}

# scatterplot completion times for mult. runs
complot.multi <- function(d, ...) {
	# calculate time to completion
	zi <- comptime2(d)
	# plot it
	xyplot(x ~ msg, zi, groups=run, xlab="message number", ylab="time to completion", type=c('g', 'p'), ...)
}

complot.hi <- function(d, special.color='red',normal.color='grey', ...) {	zi <- comptime2(d)
	xyplot(x ~ msg, zi, groups=x < 150, xlab="message number", ylab="time to completion", ylim=c(0,260), type=c('g', 'p'), par.settings = list(superpose.symbol = list(col=c('grey', 'red'))), xlim=c(-5, 1925), ...)
}

# plot operations per seconds
ops.per.sec <- function(d) {
	# ignore first producer and last consumer stages
	d <- subset(d, stage != '0-B' & stage != '3-E')
	# simplifies aggregation
	d$n <- 1
	# for per-second aggregation
	d$sec <- floor(d$ts - min(d$ts))
	# stop when last item leaves work queues, so as not to include
	# time for consumer to drain the queue
	#cutoff <- max(subset(d, stage=="3-E")$ts)
	#d <- subset(d, ts <= cutoff)
	d.agg <- aggregate(d$n, by=list(sec=d$sec), sum)
	#print(d.agg)
	yrange <- c(0, pretty(max(d.agg$x)*1.2)[1] )
	ggplot(d.agg, aes(x=sec, y=x)) + geom_line() + geom_point() +
           ylim(yrange) + xlab("Time (s)") + ylab("Operations/sec") + geom_smooth() 
}

#plot messages in flight vs. time
flight.tm.agg <- function(d) {
	# remove edge stages
	d <- subset(d, stage != '0-B' & stage != '4-E')
	# add column with '-1' for begin stage, and '1' for end stage
	# note: begin/end are from the perspective of the worker, thus
	#       begin is when it pulls a message off, end is when it puts it back
	d$flt <- 1
	d$flt[grep('B$', d$stage)] <- (-1)
	# cumsum by run
	d$sec <- floor(d$ts - min(d$ts))
	d <- d[order(d$ts),]
	ddply(d, .(run), 
		  function(data) data.frame(run=data$run,
	                                wid=data$wid,
	                                ts=data$t - min(data$t), 
	                                n=cumsum(data$flt)),
	      .parallel=TRUE
	      )
}
# assume flight.tm.agg is already applied
flight.tm <- function(d, nrow=NULL, ncol=NULL) {
	# plot each vs. time
	d$run <- factor(d$run)
	ggplot(d, aes(x=ts, y=n)) + geom_point() + facet_wrap( ~ run, nrow=nrow, ncol=ncol)
}

# Compare total runtimes for multiple runs
total.runtime <- function(d) {
	# ignore first producer and last consumer stages
	d <- subset(d, stage != '0-B' & stage != '4-E')
	# aggregate each run into its total runtime
	d.agg <- aggregate(d$t, by=list(run=d$run), function(x) max(x) - min(x))
	# also aggregate into number of distinct workers
	w.agg <- aggregate(d$wid, by=list(run=d$run), function(x) length(unique(x)))
	# make data frame of merged stuff
	df <- data.frame(workers=w.agg$x, runtime=d.agg$x, run=d.agg$run)
	df <- df[order(df$workers),]
	# plot it
	ymax = pretty(max(df$runtime)*1.1)[1]
	ggplot(df, aes(x=workers, y=runtime)) + geom_point() + 
	ylim(0,ymax) + geom_smooth() +
	xlab("Number of workers") + ylab("Total runtime (s)") + scale_x_log2()
}

#
# Compare one-vs-many completion times
# Usage: canned.onevsmany("/data", type="wakey", count=16)
# This will read the files "/data/r-1_on_16_nodes_wakey.csv" and
# "/data/r-16_on_1_node_wakey.csv" and plot them together.
#
canned.onevsmany <- function(datadir, type="sleep", count=16) 
{
	mkf <- function(d,n,t) sprintf("%s/r-%s_node%s_%s.csv", d, n,
	  ifelse(strsplit(n, "_", fixed=T)[[1]][1] == '1', 's', ''), t)
	x <- NULL
	for (n in c(sprintf("1_on_%d", count), sprintf("%d_on_1", count))) {
	  data <- csv.in(mkf(datadir, n, type))
	  data$run <- n
	  if (is.null(x)) {
	  	x <- data
	  }
	  else {
	  	x <- rbind(x, data)
	  }
	}
	complot.multi(x, auto.key=T, main=paste(type, "workers"))
}